利用JavaScript下載連結

大綱

由於保全限制,因此,客戶端的js不允與直接下載檔案.因此網路上有各種各樣的方法,這裡介紹其中一種。

相關

csv file

建立假連結

列出幾種下載檔案的javascript方法,並討論優缺點。

一般有兩種方式:

window.open
mouse click/tap on link

兩種方式都有一些問題,分別探討如下。

【方法1: window.open】

window.downloadFile = function(sUrl) {
    window.open(sUrl);
}

大部分的瀏覽器都支援window.open但是有缺點:
• 會開啟一個空白視窗
• 如果MIME的內容會被瀏覽器載入,則不會下載。

改進:
"_self" 可以避免上述第一個問題。例如,

window.downloadFile = function(sUrl) {
    window.open(sUrl, '_self');
}

【方法2: 利用mouse click 事件】
但是仍然無法解決第2個問題。但是 利用HTML5 的屬性:"download"可以避免上述第2個問題(因為在attribute 中已經指出直接下載)。

利用link而不是windows.open(),雖然不會因而產生新視窗,但是問題是,必須由使用者滑鼠觸動,因此,這裡順便利用了虛擬事件(dispatchevent)。:

    //Creating new link node.
    var link = document.createElement('a');
    link.href = sUrl;
 
    //Dispatching click event.
    if (document.createEvent) {
        var e = document.createEvent('MouseEvents');
        e.initEvent('click' ,true ,true);
        link.dispatchEvent(e);
        return true;
    }

程式碼:8-10
建立滑鼠事件 document.createEvent()
滑鼠事件的哪一個,這裡 click
由物件(link) 發出觸發事件dispatchEvent(e)

其他瀏覽器支援(跳過)

加入其他瀏覽器支援的函數 downloadFile get library from GitHub
使用方法:直接調用函數 downloadFile

檔案download.js 的全部列表:

window.downloadFile = function (sUrl) {

    //iOS devices do not support downloading. We have to inform user about this.
    if (/(iP)/g.test(navigator.userAgent)) {
        alert('Your device does not support files downloading. Please try again in desktop browser.');
        return false;
    }

    //If in Chrome or Safari - download via virtual link click
    if (window.downloadFile.isChrome || window.downloadFile.isSafari) {
        //Creating new link node.
        var link = document.createElement('a');
        link.href = sUrl;

        if (link.download !== undefined) {
            //Set HTML5 download attribute. This will prevent file from opening if supported.
            var fileName = sUrl.substring(sUrl.lastIndexOf('/') + 1, sUrl.length);
            link.download = fileName;
        }

        //Dispatching click event.
        if (document.createEvent) {
            var e = document.createEvent('MouseEvents');
            e.initEvent('click', true, true);
            link.dispatchEvent(e);
            return true;
        }
    }

    // Force file download (whether supported by server).
    if (sUrl.indexOf('?') === -1) {
        sUrl += '?download';
    }

    window.open(sUrl, '_self');
    return true;
}

window.downloadFile.isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
window.downloadFile.isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;

利用 ajax XMLHtpRequest

尚未測試

function downloadFile(urlToSend) {
     var req = new XMLHttpRequest();
     req.open("GET", urlToSend, true);
     req.responseType = "blob";
     req.onload = function (event) {
         var blob = req.response;
         var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
         var link=document.createElement('a');
         link.href=window.URL.createObjectURL(blob);
         link.download=fileName; //. 利用HTML5 的download屬性。

         link.click();
     };

     req.send();
 }

// Download a file form a url.
function saveFile(url) {
  // Get file name from url.
  var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
    a.download = filename; // Set the file name. 利用HTML5 的download屬性。
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    delete a;
  };
  xhr.open('GET', url);
  xhr.send();
}

read a server site txt file

var url = "http://www.example.com/file.json";

var jsonFile = new XMLHttpRequest();
    jsonFile.open("GET",url,true);
    jsonFile.send();

    jsonFile.onreadystatechange = function() {
        if (jsonFile.readyState== 4 && jsonFile.status == 200) {
            document.getElementById("id-of-element").innerHTML = jsonFile.responseText;
        }
     }